home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso / 1249 / sunup.t < prev    next >
Text File  |  1997-04-18  |  10KB  |  442 lines

  1. %
  2. % "sunup.t" calculates the times of sunrise and sunset
  3. % on any date, accurate to the minute within several
  4. % centuries of the present.  It correctly describes what
  5. % happens in the arctic and antarctic regions, where
  6. % the Sun may not rise or set on a given date.  
  7. % This program was adapted from a BASIC program in
  8. % Sky & Telescope magazine, August 1994, page 84,
  9. % written by Roger W. Sinnott.
  10. %
  11. % Enter north latitudes positive, west longitudes negative.  
  12. %
  13. % For the time zone, enter the number of hours west of Greenwich 
  14. % (e.g., 5 for EST, 4 for EDT).  
  15. %
  16. %   Sample program for the T Interpreter by:
  17. %
  18. %   Stephen R. Schmitt
  19. %   962 Depot Road
  20. %   Boxborough, MA 01719
  21. %
  22.  
  23. const PI : real := 2 * arcsin( 1 )
  24. const DR : real := PI / 180
  25. const K1 : real := 15 * DR * 1.0027379
  26.  
  27. var Sunrise, Sunset : boolean := false
  28.  
  29. type rvector : array[3] of real
  30.  
  31. program
  32.  
  33.     var lat, lon, tz, ph : real
  34.     var jd, ct, t0, ra0, ra1, dec0, dec1 : real
  35.     var k, zone : int
  36.     var ra, dec, v : rvector
  37.  
  38.     prompt "Latitude, +N, -S (deg):"
  39.     get lat
  40.     prompt "Longitude, +E, -W (deg):"
  41.     get lon
  42.     prompt "Time zone +West of GMT, -East (hrs):"
  43.     get zone
  44.  
  45.     jd := julian_day - 2451545  % Julian day relative to Jan 1.5, 2000
  46.     show_input( lat, lon, zone )
  47.     
  48.     lon := lon / 360
  49.     tz := zone / 24
  50.     ct := jd / 36525 + 1        % centuries since 1900.0
  51.     
  52.     t0 := lst( lon, jd, tz )
  53.     
  54.     % get sun's position
  55.     jd := jd + tz
  56.     sun( ra0, dec0, jd, ct )
  57.     jd := jd + 1
  58.     sun( ra1, dec1, jd, ct )
  59.  
  60.     if ra1 < ra0 then 
  61.         ra1 := ra1 + 2 * PI
  62.     end if
  63.  
  64.     ra[0]  := ra0
  65.     dec[0] := dec0
  66.     
  67.     for k := 0...23 do
  68.  
  69.         ph := ( k + 1 ) / 24
  70.         
  71.         ra[2]  := ra0  + ph * ( ra1  - ra0 )
  72.         dec[2] := dec0 + ph * ( dec1 - dec0 )
  73.     
  74.         test( k, zone, t0, lat, ra, dec, v )
  75.         
  76.         ra[0]  := ra[2]
  77.         dec[0] := dec[2]
  78.         
  79.     end for
  80.     
  81.     %  special message?
  82.     if ( not Sunrise ) and ( not Sunset ) then
  83.  
  84.         if v[2] < 0 then
  85.             put "Sun down all day"
  86.         else
  87.             put "Sun up all day"
  88.         end if
  89.  
  90.     else
  91.     
  92.         if not Sunrise then
  93.             put "No sunrise this date"
  94.         elsif not Sunset then
  95.             put "No sunset this date"
  96.         end if
  97.  
  98.     end if
  99.  
  100. end program
  101.  
  102. %
  103. % display latitude, longitude and time zone
  104. %
  105. procedure show_input( lat, lon : real, zone : int )
  106.  
  107.     var deg, min : int
  108.     
  109.     if sgn( zone ) = sgn( lon ) and zone ~= 0 then
  110.         put "WARNING: time zone and longitude are incompatible"
  111.     end if
  112.  
  113.     if abs( zone ) > 12 then
  114.         put "WARNING: invalid time zone"
  115.     end if        
  116.  
  117.     if abs( lat ) > 90 then
  118.         put "WARNING: invalid latitude"
  119.     end if
  120.  
  121.     if abs( lon ) > 180 then
  122.         put "WARNING: invalid longitude"
  123.     end if
  124.  
  125.     if lat > 0.0 then
  126.         deg := floor( lat )
  127.         min := floor( 60 * ( lat - deg ) )
  128.         put deg:4, ":",min:2, " N "...
  129.     else
  130.         deg := floor( -lat )
  131.         min := floor( 60 * ( -lat - deg ) )
  132.         put deg:4, ":",min:2, " S "...
  133.     end if
  134.  
  135.     if lon > 0.0 then
  136.         deg := floor( lon )
  137.         min := floor( 60 * ( lon - deg ) )
  138.         put deg:4, ":",min:2, " E"
  139.     else
  140.         deg := floor( -lon )
  141.         min := floor( 60 * ( -lon - deg ) )
  142.         put deg:4, ":",min:2, " W"
  143.     end if
  144.     
  145. end procedure
  146.  
  147. %
  148. % LST at 0h zone time
  149. %
  150. function lst( lon, jd, z : real ) : real
  151.  
  152.     var s, t0 : real
  153.     
  154.     s := 24110.5 + 8640184.812999999 * jd / 36525
  155.     s := s + 86636.6 * z + 86400 * lon
  156.     
  157.     s := s / 86400
  158.     s := s - floor( s )
  159.  
  160.     t0 := s * 360 * DR
  161.  
  162.     return t0
  163.     
  164. end function
  165.  
  166. % test an hour for an event
  167. %
  168. procedure test( k, zone : int, 
  169.                 t0, lat : real,
  170.                 var ra, dec, v : rvector )
  171.  
  172.     var ha : rvector
  173.     var a, b, c, d, e, s, z : real
  174.     var hr, min, time : real
  175.     var az, dz, hz, nz : real
  176.     var zchar : string
  177.     var zlet : string := "MLKIHGFEDCBAZNOPQRSTUVWXY"
  178.     label test_exit :
  179.     
  180.     ha[0] := t0 - ra[0] + k * K1 
  181.     ha[2] := t0 - ra[2] + k * K1 + K1 
  182.  
  183.     ha[1]  := ( ha[2]  + ha[0]  ) / 2       % hour angle at half hour
  184.     dec[1] := ( dec[2] + dec[0] ) / 2       % declination at half hour
  185.     
  186.     s := sin( lat * DR )
  187.     c := cos( lat * DR )
  188.     z := cos( 90.833 * DR )
  189.  
  190.     if k <= 0 then
  191.         v[0] := s * sin( dec[0] ) + c * cos( dec[0] ) * cos( ha[0] ) - z
  192.     end if
  193.  
  194.     v[2] := s * sin( dec[2] ) + c * cos( dec[2] ) * cos( ha[2] ) - z
  195.     
  196.     if sgn( v[0] ) = sgn( v[2] ) then
  197.         goto test_exit
  198.     end if
  199.     
  200.     v[1] := s * sin( dec[1] ) + c * cos( dec[1] ) * cos( ha[1] ) - z
  201.     
  202.     a :=  2 * v[0] - 4 * v[1] + 2 * v[2] 
  203.     b := -3 * v[0] + 4 * v[1] - v[2]
  204.     
  205.     d := b * b - 4 * a * v[0]
  206.  
  207.     if d < 0 then
  208.         goto test_exit
  209.     end if
  210.     
  211.     d := sqrt( d )
  212.     
  213.     if v[0] < 0 and v[2] > 0 then
  214.         put "Sunrise at: "...
  215.         Sunrise := true
  216.     end if
  217.     
  218.     if v[0] > 0 and v[2] < 0 then
  219.         put "Sunset at:  "...
  220.         Sunset := true
  221.     end if
  222.     
  223.     e := ( -b + d ) / ( 2 * a )
  224.     
  225.     if e > 1 or e < 0 then
  226.         e := ( -b - d ) / ( 2 * a )
  227.     end if
  228.     
  229.     % time of an event
  230.  
  231.     time := k + e + 1 / 120
  232.     
  233.     hr := floor( time )
  234.     min := floor( ( time - hr ) * 60 )
  235.  
  236.     zchar := "    "
  237.     if abs( zone ) <= 12 then
  238.         zchar[1] := zlet[zone+12]
  239.     end if
  240.  
  241.     put hr:2, ":", min:2, zchar...
  242.  
  243.     % azimuth of the sun at the event
  244.  
  245.     hz := ha[0] + e * ( ha[2] - ha[0] )
  246.     nz := -cos( dec[1] ) * sin( hz )
  247.     dz := c * sin( dec[1] ) - s * cos( dec[1] ) * cos( hz )
  248.     
  249.     az := arctan( nz / dz ) / DR
  250.     
  251.     if dz < 0 then
  252.         az := az + 180
  253.     end if
  254.     
  255.     if az < 0 then
  256.         az := az + 360
  257.     end if
  258.     
  259.     if az > 360 then
  260.         az := az - 360
  261.     end if
  262.     
  263.     put "azimuth: ", az:5:1
  264.  
  265. test_exit:
  266.  
  267.     v[0] := v[2]
  268.  
  269. end procedure
  270.  
  271. % sun's position using fundamental arguments 
  272. % (Van Flandern & Pulkkinen, 1979)
  273. %
  274. procedure sun( var ra, dec : real, jd, ct : real )
  275.  
  276.     var g, lo, s, u, v, w : real
  277.     
  278.     lo := 0.779072 + 0.00273790931 * jd
  279.     lo := lo - floor( lo )
  280.     lo := lo * 2 * PI
  281.  
  282.     g := 0.993126 + 0.0027377785 * jd
  283.     g := g - floor( g )
  284.     g := g * 2 * PI
  285.     
  286.     v := 0.39785 * sin( lo )
  287.     v := v - 0.01 * sin( lo - g )
  288.     v := v + 0.00333 * sin( lo + g )
  289.     v := v - 0.00021 * ct * sin( lo )
  290.     
  291.     u := 1 - 0.03349 * cos( g )
  292.     u := u - 0.00014 * cos( 2 * lo )
  293.     u := u + 0.00008 * cos( lo )
  294.     
  295.     w := -0.0001 - 0.04129 * sin( 2 * lo )
  296.     w := w + 0.03211 * sin( g )
  297.     w := w + 0.00104 * sin( 2 * lo - g )
  298.     w := w - 0.00035 * sin( 2 * lo + g )
  299.     w := w - 0.00008 * ct * sin( g )
  300.     
  301.     % compute sun's right ascension and declination
  302.     
  303.     s := w / sqrt( u - v * v )
  304.     ra := lo + arctan( s / sqrt( 1 - s * s ) )
  305.     s := v / sqrt( u )
  306.     dec := arctan( s / sqrt( 1 - s * s ) )
  307.  
  308. end procedure
  309.  
  310. %
  311. % determine Julian day from calendar date
  312. % ref: Jean Meeus, "Astronomical Algorithms", Willmann-Bell, 1991
  313. %
  314. function julian_day : real
  315.  
  316.     var a, b, day, jd : real
  317.     var month, year : int
  318.     var gregorian : boolean
  319.  
  320.     prompt "Year:"
  321.     get year
  322.     prompt "Month:"
  323.     get month
  324.     prompt "Day:"
  325.     get day
  326.  
  327.     date( floor( day ), month, year )
  328.     
  329.     if year < 1583 then
  330.         gregorian := false
  331.     else
  332.         gregorian := true
  333.     end if
  334.     
  335.     if month = 1 or month = 2 then
  336.         year := year - 1
  337.         month := month + 12
  338.     end if
  339.  
  340.     a := floor( year / 100 )
  341.     if gregorian then
  342.         b := 2 - a + floor( a / 4 )
  343.     else
  344.         b := 0.0
  345.     end if
  346.  
  347.     jd := floor( 365.25 * ( year + 4716 ) ) + 
  348.           floor( 30.6001 * ( month + 1 ) ) + 
  349.           day + b - 1524.5
  350.     
  351.     return jd
  352.     
  353. end function
  354.  
  355. %
  356. % display the date
  357. %
  358. procedure date( d, m, y : int )
  359.  
  360.     var day, month : array[12] of string
  361.     var mi, yi, i : int
  362.  
  363.     month[0]  := "January"
  364.     month[1]  := "February"
  365.     month[2]  := "March"
  366.     month[3]  := "April"
  367.     month[4]  := "May"
  368.     month[5]  := "June"
  369.     month[6]  := "July"
  370.     month[7]  := "August"
  371.     month[8]  := "September"
  372.     month[9]  := "October"
  373.     month[10] := "November"
  374.     month[11] := "December"
  375.  
  376.     day[0] := "Monday"
  377.     day[1] := "Tuesday"
  378.     day[2] := "Wednesday"
  379.     day[3] := "Thursday"
  380.     day[4] := "Friday"
  381.     day[5] := "Saturday"
  382.     day[6] := "Sunday"
  383.  
  384.     mi := m
  385.     yi := y
  386.  
  387.     if y < 1752 then
  388.  
  389.         put month[mi-1], " ", d, ", ", yi
  390.  
  391.     else
  392.  
  393.         if m = 1 or m = 2 then
  394.  
  395.             m := m + 12
  396.             y := y - 1
  397.  
  398.         end if
  399.  
  400.         i := d + 2*m + 3*(m+1) div 5 + y + y div 4 - y div 100 + y div 400
  401.         i := i mod 7
  402.  
  403.         put day[i], ", ", month[mi-1], " ", d, ", ", yi
  404.  
  405.     end if
  406.  
  407. end procedure
  408.  
  409. %
  410. % returns value for sign of argument
  411. %
  412. function sgn( x : real ) : int
  413.  
  414.     var rv : int
  415.     
  416.     if x > 0.0 then
  417.         rv :=  1
  418.     elsif x < 0.0 then
  419.         rv := -1
  420.     else
  421.         rv :=  0
  422.     end if
  423.  
  424.     return rv
  425.  
  426. end function
  427.  
  428. %
  429. % absolute value of argument
  430. %
  431. function abs( x : real ) : real
  432.  
  433.     if x < 0.0 then
  434.         x := -x
  435.     end if
  436.  
  437.     return x
  438.  
  439. end function